import java.util.Scanner;

public class A_3_2 {

    public int[][] dp = new int[105][200005];

    public final static int t = 100001;  //ai或者bi所有输入项和最大为100*1000 = 100000
    public final static int f = -200005;  //ai+bi所有输入项和最小为100*-1000*2 = -200000

    public int getMax(int a, int b) {
        return a > b ? a : b;
    }
    /*
     * dp[i][j]:i表示符合输入数据中ai + bi > 0的前i项，j表示这i项中ai的和
     * dp[i][j]：其具体含义为当前i项ai和为j时，存放前i项中bi和的最大值
     * 那么，可知共有n项满足ai + bi > 0，那么找出dp[n][j] + j最大值即为最终结果
     */
    public void printResult(int[] A, int[] B, int len) {
        for(int i = 0;i < len;i++) {
            for(int j = -t;j < t;j++)
                dp[i][j + t] = f;    //初始化为题目所有输入数据和最小值，即前i项中bi的和
        }
        for(int i = 0;i < len;i++) {
            //此处，使用t作为防止数组越界标准数，因为A[i]有可能小于0，而数组下标不可能为负数
            dp[i][A[i] + t] = B[i];     //初始化当j = A[i] + t时，此时前i项B的和为B[i]
        }
        for(int i = 1;i < len;i++) {
            for(int j = -t;j < t;j++) {
                dp[i][j + t] = getMax(dp[i - 1][j + t], dp[i][j + t]);
                if(j + t - A[i] < 0 || j + t - A[i] > 200001)
                    continue;
                //此处判定，作为当j + t中不包含第i项A[i]时，更新当前最大值
                dp[i][j + t] = getMax(dp[i][j + t], dp[i - 1][j + t - A[i]] + B[i]);
            }
        }
        int result = f;
        for(int i = 0;i < t;i++) {
            //可知，最终的dp[i][j]中，其中j >= t，dp[i][j] >= 0，才符合对于sum(ai)和sum(bi)均不小于0的要求
            if(dp[len - 1][i + t] >= 0)
                result = getMax(result, dp[len - 1][i + t] + i);
        }
        if(result <= 0) {
            System.out.println(0);
            return;
        }
        System.out.println(result);
    }


    public static void main(String[] args) {
        A_3_2 test = new A_3_2();
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int len = 1;
        int[] A = new int[n + 1];
        int[] B = new int[n + 1];
        for(int i = 1;i <= n;i++) {
            int a = in.nextInt();
            int b = in.nextInt();
            if(a + b > 0) { //过滤掉所有a + b <= 0的数据对
                A[len] = a;
                B[len++] = b;
            }
        }
        test.printResult(A, B, len);
    }
}








//import java.util.Scanner;
//
//public class A_3_2 {
//    public static int [] arrLeft = null;
//    public static int [] arrRight = null;
//    public static int [][] dp = new int[101][200001];//[i][j]i:第几次\\\j 消耗  dp价值
//    public static void main(String[] args) {
//        Scanner in = new Scanner(System.in);
//        int n = in.nextInt();
//        arrLeft = new int[n];
//        arrRight = new int[n];
//        for(int i=0;i<n;i++){
//            arrLeft[i] = in.nextInt();//ai
//            arrRight[i] = in.nextInt();//bi输入值
//        }
//        for(int i=0;i<dp.length;i++){
//            for(int j=0;j<dp[0].length;j++){
//                dp[i][j] = -999999;//初始化
//            }
//        }
//        int t = 100000;// -100000<=t<=100000//两边同时加100000重新规定0
//
//        /*
//          1<=n<=100
//          　　-1000<=ai,bi<=1000
//         */
//        for(int i=0;i<n;i++){
//            dp[i][t+arrLeft[i]] = arrRight[i];//初始化
//        }
//
//        for(int i=1;i<n;i++){
//            for(int j=0;j<dp[0].length;j++){
//                dp[i][j] = Math.max(dp[i][j],dp[i-1][j]);//看看对应上一个的大小
//                if(j-arrLeft[i]<0||j-arrLeft[i]>200000)
//                    continue;
//                dp[i][j] = Math.max(arrRight[i]+dp[i-1][j-arrLeft[i]],dp[i][j]);
//            }
//        }
//        int ans = -999999;
//        for(int i=0;i<=t;i++){
//            if(dp[n-1][i+t]>=0)
//                ans = Math.max(ans,dp[n-1][i+t]+i);
//        }
//        if(ans==-999999)
//            System.out.println(0);
//        else
//            System.out.println(ans);
//    }
//}